package com.hibernate.hql;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.classic.Session;
import org.junit.Test;

import com.hibernate.domain.Classes;
import com.hibernate.domain.ClassesView;
import com.hibernate.domain.Student;
import com.hibernate.utils.HibernateUtil;

/**
 * hibernate之hql一对多关系查询测试类
 * @author LC
 *
 */
public class OneToManyQueryTest extends HibernateUtil {
	
	/**
	 * 等值连接——返回结果只能先以内存结构类型接收，然后再强制转换成需要的类型，结构不方便操作
	 */
	@Test
	public void testQuery_EqualValue() {
		Session session = sessionFactory.openSession() ;
		String hql = "from Classes c, Student s where c.cid = s.classes.cid" ;
		List<Object[]> list = session.createQuery(hql).list() ;
		Iterator<Object[]> iterator = list.iterator() ;
		while(iterator.hasNext()) {
			Object[] objects = iterator.next() ;
			for (Object object : objects) {
				if(object instanceof Classes) {
					Classes classes = (Classes) object ;
					System.out.println(classes);
				} else if(object instanceof Student) {
					Student student = (Student) object ;
					System.out.println(student);
				}
			}
		}
		session.close() ;
	}
	
	/**
	 * 内连接——返回结果只能先以内存结构类型接收，然后再强制转换成需要的类型，结构不方便操作
	 */
	@Test
	public void testQuery_InnerJoin() {
		Session session = sessionFactory.openSession() ;
		String hql = "from Classes c inner join c.students s" ;
		List<Object[]> list = session.createQuery(hql).list() ;
		Iterator<Object[]> iterator = list.iterator() ;
		while(iterator.hasNext()) {
			Object[] objects = iterator.next() ;
			for (Object object : objects) {
				if(object instanceof Classes) {
					Classes classes = (Classes) object ;
					System.out.println(classes);
				} else if(object instanceof Student) {
					Student student = (Student) object ;
					System.out.println(student);
				}
			}
		}
		session.close() ;
	}
	
	/**
	 * 迫切内连接——返回迫切内连接的对象集合，结构简单实用
	 */
	@Test
	public void testQuery_innerJoin_fetch() {
		Session session = sessionFactory.openSession() ;
		String hql = "from Classes c inner join fetch c.students s" ;
		List<Classes> list = session.createQuery(hql).list() ;
		for (Classes classes : list) {
			System.out.println(classes);
			Set<Student> students = classes.getStudents() ;
			for (Student student : students) {
				System.out.println(student);
			}
		}
		
		session.close() ;
	}
	

	/**
	 * 左外连接——返回结果只能先以内存结构类型接收，然后再强制转换成需要的类型，结构不方便操作
	 */
	@Test
	public void testQuery_leftOuterJoin() {
		Session session = sessionFactory.openSession() ;
		String hql = "from Classes c left outer join c.students s" ;
		List<Object[]> list = session.createQuery(hql).list() ;
		for (Object[] objects : list) {
			for (int i = 0; i < objects.length; i++) {
				if(objects[i] instanceof Classes) {
					Classes classes = (Classes) objects[i] ;
					System.out.println(classes) ;
				} else if (objects[i] instanceof Student) {
					Student student = (Student) objects[i] ;
					System.out.println(student);
				}
			}
		}
		session.close() ;
	}
	
	/**
	 * 迫切左外连接——返回迫切左外连接的对象集合
	 * 注意：
	 * 		通过以上测试发现，迫切连接与普通连接内存数据结构是不同的，且迫切连接的内存结构相对简单实用
	 */
	@Test
	public void testQuery_leftOuterJoin_fetch() {
		Session session = sessionFactory.openSession() ;
		String hql = "from Classes c left outer join fetch c.students s" ;
		List<Classes> list = session.createQuery(hql).list() ;
		for (Classes classes : list) {
			System.out.println(classes);
			Set<Student> students = classes.getStudents() ;
			for (Student student : students) {
				System.out.println(student);
			}
		}
		session.close() ;
	}
	
	/**
	 * 查询classes表中的name和student表中的name
	 *   带构造函数的select查询的内存数据结构和fetch的内存数据结构是矛盾的，所以两者不能在一起使用
	 */
	@Test
	public void testQuery_innerJoin_Constrcutor() {
		Session session = sessionFactory.openSession() ;
		String hql = "select new com.hibernate.domain.ClassesView(c.cname, s.sname)" +
				"from Classes c inner join c.students s" ;
		List<ClassesView> list = session.createQuery(hql).list() ;
		for (ClassesView classesView : list) {
			System.out.println(classesView);
		}
		session.close() ;
	}
}
